import path from 'path';
import { ITransaction, TransactionStatus } from '../interfaces/ITransaction';
import { TransactionConfig, OperationResult } from '../types';
import { FileSystem } from '../utils/fileSystem';

/**
 * 事务类
 */
export class Transaction implements ITransaction {
    /** 事务ID */
    private readonly id: string;
    
    /** 事务配置 */
    private readonly config: TransactionConfig;
    
    /** 事务路径 */
    private readonly transactionPath: string;
    
    /** 日志文件路径 */
    private readonly logPath: string;
    
    /** 事务状态 */
    private status: TransactionStatus;
    
    /** 事务操作记录 */
    private operations: Array<{
        type: 'write' | 'delete';
        path: string;
        data?: any;
        backup?: any;
    }>;

    /**
     * 构造函数
     * @param config 事务配置
     * @param dbPath 数据库路径
     */
    constructor(config: TransactionConfig, dbPath: string) {
        this.id = config.id;
        this.config = config;
        this.transactionPath = path.join(dbPath, 'transactions');
        this.logPath = path.join(this.transactionPath, `${this.id}.log`);
        this.status = TransactionStatus.INITIAL;
        this.operations = [];
    }

    /**
     * 获取事务ID
     */
    getId(): string {
        return this.id;
    }

    /**
     * 开始事务
     */
    async begin(): Promise<void> {
        if (this.status !== TransactionStatus.INITIAL) {
            throw new Error('Transaction already started');
        }

        await FileSystem.ensureDir(this.transactionPath);
        await this.saveTransactionLog();
        this.status = TransactionStatus.ACTIVE;
    }

    /**
     * 提交事务
     */
    async commit(): Promise<void> {
        if (this.status !== TransactionStatus.ACTIVE) {
            throw new Error('Transaction not active');
        }

        try {
            // 清理备份
            for (const operation of this.operations) {
                const backupPath = this.getBackupPath(operation.path);
                await FileSystem.removeFile(backupPath);
            }

            this.status = TransactionStatus.COMMITTED;
            await this.saveTransactionLog();
            await FileSystem.removeFile(this.logPath);
        } catch (error) {
            this.status = TransactionStatus.ERROR;
            throw error;
        }
    }

    /**
     * 回滚事务
     */
    async rollback(): Promise<void> {
        if (this.status !== TransactionStatus.ACTIVE) {
            throw new Error('Transaction not active');
        }

        try {
            // 恢复备份
            for (const operation of this.operations.reverse()) {
                const backupPath = this.getBackupPath(operation.path);
                if (await FileSystem.exists(backupPath)) {
                    const backup = await FileSystem.readJson(backupPath);
                    if (operation.type === 'write') {
                        await FileSystem.writeJson(operation.path, backup);
                    } else if (operation.type === 'delete') {
                        await FileSystem.removeFile(operation.path);
                    }
                    await FileSystem.removeFile(backupPath);
                }
            }

            this.status = TransactionStatus.ROLLED_BACK;
            await this.saveTransactionLog();
            await FileSystem.removeFile(this.logPath);
        } catch (error) {
            this.status = TransactionStatus.ERROR;
            throw error;
        }
    }

    /**
     * 执行数据库操作
     * @param operation 操作函数
     */
    async execute(operation: () => Promise<OperationResult>): Promise<OperationResult> {
        if (this.status !== TransactionStatus.ACTIVE) {
            throw new Error('Transaction not active');
        }

        try {
            const result = await operation();
            if (!result.success) {
                await this.rollback();
            }
            return result;
        } catch (error) {
            await this.rollback();
            throw error;
        }
    }

    /**
     * 获取事务状态
     */
    getStatus(): TransactionStatus {
        return this.status;
    }

    /**
     * 记录写操作
     * @param path 文件路径
     * @param data 数据
     */
    async recordWrite(path: string, data: any): Promise<void> {
        const backupPath = this.getBackupPath(path);
        
        // 创建备份
        if (await FileSystem.exists(path)) {
            const backup = await FileSystem.readJson(path);
            await FileSystem.writeJson(backupPath, backup);
        }

        this.operations.push({
            type: 'write',
            path,
            data
        });

        await this.saveTransactionLog();
    }

    /**
     * 记录删除操作
     * @param path 文件路径
     */
    async recordDelete(path: string): Promise<void> {
        const backupPath = this.getBackupPath(path);
        
        // 创建备份
        if (await FileSystem.exists(path)) {
            const backup = await FileSystem.readJson(path);
            await FileSystem.writeJson(backupPath, backup);
        }

        this.operations.push({
            type: 'delete',
            path
        });

        await this.saveTransactionLog();
    }

    /**
     * 获取备份文件路径
     * @param originalPath 原始文件路径
     */
    private getBackupPath(originalPath: string): string {
        const fileName = path.basename(originalPath);
        return path.join(this.transactionPath, `${this.id}_${fileName}.backup`);
    }

    /**
     * 保存事务日志
     */
    private async saveTransactionLog(): Promise<void> {
        const log = {
            id: this.id,
            status: this.status,
            operations: this.operations,
            timestamp: new Date().toISOString()
        };
        await FileSystem.writeJson(this.logPath, log);
    }
}
